/*************************************************************
*
* M3D_CTRL.H
*
*************************************************************/

#ifndef _M3D_CTRL_H_
#define _M3D_CTRL_H_

#define M3D_CTRL_ST_ENABLE          0x0001
#define M3D_CTRL_ST_DISABLE_AT_END  0x0002
#define M3D_CTRL_ST_NON_PERIODIC    0x0004

//
// Basic controller types
//
enum {
   M3D_CTRL_TIME,      // == GENERIC
   M3D_CTRL_3D_POS_SPLINE,

   M3D_CTRL_MAX,
};

//
// Time controller
//
class m3dCTRL_TIME {
   float       timeCur;
   float       period;     // animation period
   float       speed;      // animation speed

protected:
   int         typeCtrl;

public:
   apSTATE     state;

public:
   m3dCTRL_TIME          (float _period) : timeCur(0.f), period(_period), speed(1.f), typeCtrl(M3D_CTRL_TIME) { Enable(TRUE); }
   m3dCTRL_TIME          (void) : timeCur(0.f), period(1.f), speed(1.f), typeCtrl(M3D_CTRL_TIME) { Enable(TRUE); }
   virtual ~m3dCTRL_TIME (void) {}; 

   virtual void Update   (float elapsedTime);
   virtual void Enable   (BOOL _isEnable) { (_isEnable) ? state.Set(M3D_CTRL_ST_ENABLE): state.Clear(M3D_CTRL_ST_ENABLE); }
   BOOL         IsEnabled(void)           { return state.Is(M3D_CTRL_ST_ENABLE);  }
   
   void   SetTimeCur     (float _timeCur) { if (IsEnabled()) timeCur    = _timeCur;  }
   float  GetTimeCur     (void)           { return timeCur; }

   void   SetPeriod      (float _period)  { period     = _period; }
   float  GetPeriod      (void)           { return period;        }
   void   SetSpeed       (float _speed)   { speed      = _speed;  }

   float  GetCoeff       (void)           { return m3dClamp(0.f, 1.f, 0.f, period, timeCur); }

   int    GetTypeCtrl    (void)           { return typeCtrl; }
};


class m3dCTRL_1D : public m3dCTRL_TIME {
protected:
   float   val;
public:
   m3dCTRL_1D          (float _period) : m3dCTRL_TIME(_period), val(0.f) {}
   m3dCTRL_1D          (void) : m3dCTRL_TIME(), val(0.f) {}
   virtual ~m3dCTRL_1D (void) {}

   virtual void   GetValue    (float *_val) { *_val = val; }
   virtual void   SetValue    (float *_val) { val = *_val; }
   virtual float  GetMaxValue (void)        { return val; }
};

class m3dCTRL_3D : public m3dCTRL_TIME {
protected:
   m3dV    val;
public:
   m3dCTRL_3D          (float _period) : m3dCTRL_TIME(_period), val(m3dVZero) {}
   m3dCTRL_3D          (void) : m3dCTRL_TIME(), val(m3dVZero) {}
   virtual ~m3dCTRL_3D (void) {}

   virtual void GetValue (m3dV *_val) { *_val = val; }
   virtual void SetValue (m3dV *_val) { val = *_val; }
};

class m3dCTRL_CONSTR : public m3dCTRL_TIME {
protected:
   m3dMATR    val;
public:
   m3dCTRL_CONSTR          (float _period) : m3dCTRL_TIME(_period), val(m3dMatrIdentity) {}
   m3dCTRL_CONSTR          (void) : m3dCTRL_TIME(), val(m3dMatrIdentity) {}
   virtual ~m3dCTRL_CONSTR (void) {}

   virtual void GetValue (m3dMATR *_val) { *_val = val; }
   virtual void SetValue (m3dMATR *_val) { val = *_val; }
};

class m3dCTRL_COLOR : public m3dCTRL_TIME {
protected:
   m3dCOLOR   val;
public:
   m3dCTRL_COLOR          (float _period) : m3dCTRL_TIME(_period), val() {}
   m3dCTRL_COLOR          (void) : m3dCTRL_TIME(), val() {}
   virtual ~m3dCTRL_COLOR (void) {}

   virtual void GetValue (m3dCOLOR *_val) { *_val = val; }
   virtual void SetValue (m3dCOLOR *_val) { val = *_val; }
};

//
// Spline controllers
//
class m3dCTRL_1D_SPL : public m3dCTRL_1D {
   m3dSPL_LINEAR1D  *pSpl;
public:
   m3dCTRL_1D_SPL          (float _period, m3dSPL_LINEAR1D *_pSpl) :  m3dCTRL_1D(_period), pSpl(_pSpl) { };
   virtual ~m3dCTRL_1D_SPL (void) { delete pSpl; }

   virtual void     GetValue   (float *val);
   void             SetSpline  (m3dSPL_LINEAR1D *_pSpl) { pSpl = _pSpl; }
   m3dSPL_LINEAR1D* GetSpline  (void)                   { return pSpl;  }
   virtual float    GetMaxValue(void);
};


class m3dCTRL_3D_SPL : public m3dCTRL_3D {
   m3dSPL_LINEAR3D  *pSpl;
public:
   m3dCTRL_3D_SPL          (float _period, m3dSPL_LINEAR3D *_pSpl) : m3dCTRL_3D(_period), pSpl(_pSpl) { typeCtrl = M3D_CTRL_3D_POS_SPLINE; }
   virtual ~m3dCTRL_3D_SPL (void) { delete pSpl; }

   virtual void     GetValue   (m3dV *val);
   void             SetSpline  (m3dSPL_LINEAR3D *_pSpl) { pSpl = _pSpl; }
   m3dSPL_LINEAR3D* GetSpline  (void)                   { return pSpl;  }
};

class m3dCTRL_COLOR_SPL : public m3dCTRL_COLOR {
   m3dSPL_COLOR *pSpl;
public:
   m3dCTRL_COLOR_SPL          (float _period, m3dSPL_COLOR *_pSpl) :  m3dCTRL_COLOR(_period), pSpl(_pSpl) { };
   virtual ~m3dCTRL_COLOR_SPL (void) { delete pSpl; }

   virtual void  GetValue   (m3dCOLOR *val);
   void          SetSpline  (m3dSPL_COLOR *_pSpl) { pSpl = _pSpl; }
   m3dSPL_COLOR* GetSpline  (void)                { return pSpl;  }
};


//
// Noise controllers
//
class m3dCTRL_1D_NOISE : public m3dCTRL_1D {
   m3dNOISE *pNoise;
   float     minVal, maxVal;
   float     freq;
public:
   m3dCTRL_1D_NOISE (m3dNOISE *_pNoise, float _minVal, float _maxVal, float _freq) : m3dCTRL_1D (), pNoise(_pNoise), minVal(_minVal), maxVal(_maxVal), freq(_freq) { state.Set(M3D_CTRL_ST_NON_PERIODIC); };
   m3dCTRL_1D_NOISE (m3dNOISE *_pNoise) : m3dCTRL_1D (), pNoise(_pNoise) { state.Set(M3D_CTRL_ST_NON_PERIODIC); };
   virtual ~m3dCTRL_1D_NOISE() {};

   virtual void   GetValue      (float *val);
   void           SetNoise      (m3dNOISE *_pNoise) { pNoise = _pNoise; }
   m3dNOISE*      GetNoise      (void)              { return pNoise;    }
   void           SetNoiseParam (float _minVal, float _maxVal, float _freq) { minVal = _minVal, maxVal = _maxVal; freq = _freq; }
   virtual float  GetMaxValue   (void);
};

class m3dCTRL_COLOR_NOISE : public m3dCTRL_COLOR {
   m3dNOISE *pNoise;
   float     minVal, maxVal;
   float     freq;
   m3dCOLOR  colorBase;
public:
   m3dCTRL_COLOR_NOISE (m3dNOISE *_pNoise, float _minVal, float _maxVal, float _freq, m3dCOLOR _colorBase) : pNoise(_pNoise), minVal(_minVal), maxVal(_maxVal), freq(_freq), colorBase(_colorBase) { state.Set(M3D_CTRL_ST_NON_PERIODIC); };
   virtual ~m3dCTRL_COLOR_NOISE() {};

   virtual void GetValue      (m3dCOLOR *val);
   void         SetNoise      (m3dNOISE *_pNoise) { pNoise = _pNoise; }
   void         SetNoiseParam (float _minVal, float _maxVal, float _freq) { minVal = _minVal, maxVal = _maxVal; freq = _freq; }
};

//
// Range
//
class m3dRANGE {
public:
   float   bot;
   float   top; 

   m3dRANGE(void) : bot(0), top(0) {}
   m3dRANGE(float _bot, float _top) {bot = _bot; top = _top;}
};


#endif // _M3D_CTRL_H_

//
// End-of-file M3D_CTRL.H
//
